package com.example.blog_system.service.impl;

import com.example.blog_system.dto.ArticleDto;
import com.example.blog_system.entity.Article;
import com.example.blog_system.entity.Tag;
import com.example.blog_system.entity.User;
import com.example.blog_system.repository.ArticleRepository;
import com.example.blog_system.repository.TagRepository;
import com.example.blog_system.repository.UserRepository;
import com.example.blog_system.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private TagRepository tagRepository;

    @Override
    @Transactional
    public ArticleDto createArticle(ArticleDto articleDto, Long authorId) {
        User author = userRepository.findById(authorId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));

        Article article = new Article();
        article.setTitle(articleDto.getTitle());
        article.setContent(articleDto.getContent());
        article.setAuthor(author);
        article.setTags(getOrCreateTags(articleDto.getTags()));

        Article savedArticle = articleRepository.save(article);
        return convertToDto(savedArticle);
    }

    @Override
    @Transactional
    public ArticleDto updateArticle(Long id, ArticleDto articleDto, Long authorId) {
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("文章不存在"));

        if (!article.getAuthor().getId().equals(authorId)) {
            throw new RuntimeException("无权修改此文章");
        }

        article.setTitle(articleDto.getTitle());
        article.setContent(articleDto.getContent());
        article.setTags(getOrCreateTags(articleDto.getTags()));

        Article updatedArticle = articleRepository.save(article);
        return convertToDto(updatedArticle);
    }

    @Override
    @Transactional
    public void deleteArticle(Long id, Long authorId) {
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("文章不存在"));

        if (!article.getAuthor().getId().equals(authorId)) {
            throw new RuntimeException("无权删除此文章");
        }

        articleRepository.delete(article);
    }

    @Override
    public ArticleDto getArticleById(Long id) {
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("文章不存在"));
        return convertToDto(article);
    }

    @Override
    public Page<ArticleDto> getAllArticles(Pageable pageable) {
        return articleRepository.findAll(pageable)
                .map(this::convertToDto);
    }

    @Override
    public Page<ArticleDto> getArticlesByAuthor(Long authorId, Pageable pageable) {
        return articleRepository.findByAuthorId(authorId, pageable)
                .map(this::convertToDto);
    }

    @Override
    public Page<ArticleDto> searchArticles(String keyword, Pageable pageable) {
        return articleRepository.searchByKeyword(keyword, pageable)
                .map(this::convertToDto);
    }

    @Override
    public Page<ArticleDto> getArticlesByTag(String tagName, Pageable pageable) {
        return articleRepository.findByTagName(tagName, pageable)
                .map(this::convertToDto);
    }

    private Set<Tag> getOrCreateTags(Set<String> tagNames) {
        if (tagNames == null) {
            return new HashSet<>();
        }

        return tagNames.stream()
                .map(name -> tagRepository.findByName(name)
                        .orElseGet(() -> {
                            Tag tag = new Tag();
                            tag.setName(name);
                            return tagRepository.save(tag);
                        }))
                .collect(Collectors.toSet());
    }

    private ArticleDto convertToDto(Article article) {
        ArticleDto dto = new ArticleDto();
        dto.setId(article.getId());
        dto.setTitle(article.getTitle());
        dto.setContent(article.getContent());
        dto.setAuthorId(article.getAuthor().getId());
        dto.setAuthorName(article.getAuthor().getUsername());
        dto.setCreatedAt(article.getCreatedAt());
        dto.setUpdatedAt(article.getUpdatedAt());
        dto.setCommentCount(article.getComments().size());
        dto.setTags(article.getTags().stream()
                .map(Tag::getName)
                .collect(Collectors.toSet()));
        return dto;
    }
} 